added samples
[windows-sources.git] / sdk / samples / all in on code / Visual Studio 2008 / CppAutomateOutlook / Solution2.cpp
blobdfe7eca43a001a690c7d066899a2e34841f67702
1 /****************************** Module Header ******************************\
2 * Module Name: Solution2.cpp
3 * Project: CppAutomateOutlook
4 * Copyright (c) Microsoft Corporation.
5 *
6 * The code in Solution2.h/cpp demontrates the use of C/C++ and the COM APIs
7 * to automate Outlook. The raw automation is much more difficult, but it is
8 * sometimes necessary to avoid the overhead with MFC, or problems with
9 * #import. Basically, you work with such APIs as CoCreateInstance(), and COM
10 * interfaces such as IDispatch and IUnknown.
12 * This source is subject to the Microsoft Public License.
13 * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
14 * All other rights reserved.
16 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
17 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
19 \***************************************************************************/
21 #pragma region Includes
22 #include <stdio.h>
23 #include <windows.h>
24 #include "Solution2.h"
25 #pragma endregion
29 // FUNCTION: AutoWrap(int, VARIANT*, IDispatch*, LPOLESTR, int,...)
31 // PURPOSE: Automation helper function. It simplifies most of the low-level
32 // details involved with using IDispatch directly. Feel free to use it
33 // in your own implementations. One caveat is that if you pass multiple
34 // parameters, they need to be passed in reverse-order.
36 // PARAMETERS:
37 // * autoType - Could be one of these values: DISPATCH_PROPERTYGET,
38 // DISPATCH_PROPERTYPUT, DISPATCH_PROPERTYPUTREF, DISPATCH_METHOD.
39 // * pvResult - Holds the return value in a VARIANT.
40 // * pDisp - The IDispatch interface.
41 // * ptName - The property/method name exposed by the interface.
42 // * cArgs - The count of the arguments.
44 // RETURN VALUE: An HRESULT value indicating whether the function succeeds
45 // or not.
47 // EXAMPLE:
48 // AutoWrap(DISPATCH_METHOD, NULL, pDisp, L"call", 2, parm[1], parm[0]);
50 HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp,
51 LPOLESTR ptName, int cArgs...)
53 // Begin variable-argument list
54 va_list marker;
55 va_start(marker, cArgs);
57 if (!pDisp)
59 _putws(L"NULL IDispatch passed to AutoWrap()");
60 _exit(0);
61 return E_INVALIDARG;
64 // Variables used
65 DISPPARAMS dp = { NULL, NULL, 0, 0 };
66 DISPID dispidNamed = DISPID_PROPERTYPUT;
67 DISPID dispID;
68 HRESULT hr;
70 // Get DISPID for name passed
71 hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
72 if (FAILED(hr))
74 wprintf(L"IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx\n",
75 ptName, hr);
76 _exit(0);
77 return hr;
80 // Allocate memory for arguments
81 VARIANT *pArgs = new VARIANT[cArgs + 1];
82 // Extract arguments...
83 for(int i=0; i < cArgs; i++)
85 pArgs[i] = va_arg(marker, VARIANT);
88 // Build DISPPARAMS
89 dp.cArgs = cArgs;
90 dp.rgvarg = pArgs;
92 // Handle special-case for property-puts
93 if (autoType & DISPATCH_PROPERTYPUT)
95 dp.cNamedArgs = 1;
96 dp.rgdispidNamedArgs = &dispidNamed;
99 // Make the call
100 hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT,
101 autoType, &dp, pvResult, NULL, NULL);
102 if (FAILED(hr))
104 wprintf(L"IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx\n",
105 ptName, dispID, hr);
106 _exit(0);
107 return hr;
110 // End variable-argument section
111 va_end(marker);
113 delete[] pArgs;
115 return hr;
119 DWORD WINAPI AutomateOutlookByCOMAPI(LPVOID lpParam)
121 // Initializes the COM library on the current thread and identifies
122 // the concurrency model as single-thread apartment (STA).
123 // [-or-] CoInitialize(NULL);
124 // [-or-] CoCreateInstance(NULL);
125 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
127 // Define vtMissing for optional parameters in some calls.
128 VARIANT vtMissing;
129 vtMissing.vt = VT_EMPTY;
132 /////////////////////////////////////////////////////////////////////////
133 // Start Microsoft Outlook and log on with your profile.
136 // Get CLSID of the server
138 CLSID clsid;
139 HRESULT hr;
141 // Option 1. Get CLSID from ProgID using CLSIDFromProgID.
142 LPCOLESTR progID = L"Outlook.Application";
143 hr = CLSIDFromProgID(progID, &clsid);
144 if (FAILED(hr))
146 wprintf(L"CLSIDFromProgID(\"%s\") failed w/err 0x%08lx\n", progID, hr);
147 return 1;
149 // Option 2. Build the CLSID directly.
150 /*const IID CLSID_Application =
151 {0x0006F03A,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
152 clsid = CLSID_Application;*/
154 // Start the server and get the IDispatch interface
156 IDispatch *pOutlookApp = NULL;
157 hr = CoCreateInstance( // [-or-] CoCreateInstanceEx, CoGetObject
158 clsid, // CLSID of the server
159 NULL,
160 CLSCTX_LOCAL_SERVER, // Outlook.Application is a local server
161 IID_IDispatch, // Query the IDispatch interface
162 (void **)&pOutlookApp); // Output
164 if (FAILED(hr))
166 wprintf(L"Outlook is not registered properly w/err 0x%08lx\n", hr);
167 return 1;
170 _putws(L"Outlook.Application is started");
172 _putws(L"User logs on ...");
174 // Get the namespace and the logon.
176 // pNS = pOutlookApp->GetNamespace("MAPI")
177 IDispatch *pNS = NULL;
179 VARIANT x;
180 x.vt = VT_BSTR;
181 x.bstrVal = SysAllocString(L"MAPI");
183 VARIANT result;
184 VariantInit(&result);
185 AutoWrap(DISPATCH_METHOD, &result, pOutlookApp, L"GetNamespace", 1, x);
186 pNS = result.pdispVal;
188 VariantClear(&x);
191 // Log on by using a dialog box to choose the profile.
192 // pNS->Logon(vtMissing, vtMissing, true, true)
194 VARIANT vtShowDialog;
195 vtShowDialog.vt = VT_BOOL;
196 vtShowDialog.boolVal = VARIANT_TRUE;
197 VARIANT vtNewSession;
198 vtNewSession.vt = VT_BOOL;
199 vtNewSession.boolVal = VARIANT_TRUE;
201 AutoWrap(DISPATCH_METHOD, NULL, pNS, L"Logon", 4, vtNewSession,
202 vtShowDialog, vtMissing, vtMissing);
205 // Alternative logon method that uses a specific profile.
206 // If you use this logon method, change the profile name to an
207 // appropriate value. The second parameter of Logon is the password (if
208 // any) associated with the profile. This parameter exists only for
209 // backwards compatibility and for security reasons, and it is not
210 // recommended for use.
211 // pNS->Logon(L"YourValidProfile", vtMissing, false, true);
213 // VARIANT vtProfile;
214 // vtProfile.vt = VT_BSTR;
215 // vtProfile.bstrVal = SysAllocString(L"YourValidProfile");
216 // VARIANT vtShowDialog;
217 // vtShowDialog.vt = VT_BOOL;
218 // vtShowDialog.boolVal = VARIANT_TRUE;
219 // VARIANT vtNewSession;
220 // vtNewSession.vt = VT_BOOL;
221 // vtNewSession.boolVal = VARIANT_TRUE;
223 // AutoWrap(DISPATCH_METHOD, NULL, pNS, L"Logon", 4, vtNewSession,
224 // vtShowDialog, vtMissing, vtProfile);
226 // VariantClear(&vtProfile);
229 wprintf(L"Press ENTER to continue when Outlook is ready.");
230 getwchar();
233 /////////////////////////////////////////////////////////////////////////
234 // Enumerate the contact items.
237 _putws(L"Enumerate the contact items");
239 // pCtFolder = pNS->GetDefaultFolder(Outlook::olFolderContacts);
240 IDispatch *pCtFolder = NULL;
242 VARIANT x;
243 x.vt = VT_I4;
244 x.lVal = 10; // Outlook::olFolderContacts
246 VARIANT result;
247 VariantInit(&result);
248 AutoWrap(DISPATCH_METHOD, &result, pNS, L"GetDefaultFolder", 1, x);
249 pCtFolder = result.pdispVal;
252 // pCts = pCtFolder->Items;
253 IDispatch *pCts = NULL;
255 VARIANT result;
256 VariantInit(&result);
257 AutoWrap(DISPATCH_PROPERTYGET, &result, pCtFolder, L"Items", 0);
258 pCts = result.pdispVal;
261 // Enumerate the contact items.
263 // Get the count of items.
264 long lCtsCount;
266 VARIANT result;
267 VariantInit(&result);
268 AutoWrap(DISPATCH_PROPERTYGET, &result, pCts, L"Count", 0);
269 lCtsCount = result.lVal;
272 for (long i = 1; i <= lCtsCount; i++)
274 // Get the item at i
275 // pItem = pCts->Item(i);
276 IDispatch *pItem = NULL;
278 VARIANT x;
279 x.vt = VT_I4;
280 x.lVal = i;
282 VARIANT result;
283 VariantInit(&result);
284 AutoWrap(DISPATCH_PROPERTYGET, &result, pCts, L"Item", 1, x);
285 pItem = result.pdispVal;
288 // Attemp to QI _ContactItem
289 const IID IID_ContactItem =
290 {0x00063021,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
291 IDispatch *pCt = NULL;
293 hr = pItem->QueryInterface(IID_ContactItem, (void **)&pCt);
294 if (SUCCEEDED(hr))
296 // pCt->Email1Address
297 VARIANT vtAddress;
298 VariantInit(&vtAddress);
299 AutoWrap(DISPATCH_PROPERTYGET, &vtAddress, pCt,
300 L"Email1Address", 0);
301 wprintf(L"%s\n", (LPCWSTR)vtAddress.bstrVal);
302 VariantClear(&vtAddress);
304 pCt->Release();
308 // Attemp to QI _DistListItem
309 const IID IID_DistListItem =
310 {0x00063081,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
311 IDispatch *pDL = NULL;
313 hr = pItem->QueryInterface(IID_DistListItem, (void **)&pDL);
314 if (SUCCEEDED(hr))
316 // pDL->DLName
317 VARIANT vtDLName;
318 VariantInit(&vtDLName);
319 AutoWrap(DISPATCH_PROPERTYGET, &vtDLName, pDL, L"DLName", 0);
320 wprintf(L"%s\n", (LPCWSTR)vtDLName.bstrVal);
321 VariantClear(&vtDLName);
323 pDL->Release();
327 // Release the interface.
328 pItem->Release();
332 /////////////////////////////////////////////////////////////////////////
333 // Create and send a new mail item.
336 _putws(L"Create and send a new mail item");
338 // pMail = pOutlookApp->CreateItem(Outlook::olMailItem);
339 IDispatch *pMail = NULL;
341 VARIANT x;
342 x.vt = VT_I4;
343 x.lVal = 0; // Outlook::olMailItem
345 VARIANT result;
346 VariantInit(&result);
347 AutoWrap(DISPATCH_METHOD, &result, pOutlookApp, L"CreateItem", 1, x);
348 pMail = result.pdispVal;
351 // Set the properties of the email.
353 // pMail->Subject = _bstr_t(L"Feedback of All-In-One Code Framework");
355 VARIANT x;
356 x.vt = VT_BSTR;
357 x.bstrVal = SysAllocString(L"Feedback of All-In-One Code Framework");
358 AutoWrap(DISPATCH_PROPERTYPUT, NULL, pMail, L"Subject", 1, x);
359 VariantClear(&x);
362 // pMail->To = _bstr_t(L"codefxf@microsoft.com");
364 VARIANT x;
365 x.vt = VT_BSTR;
366 x.bstrVal = SysAllocString(L"codefxf@microsoft.com");
367 AutoWrap(DISPATCH_PROPERTYPUT, NULL, pMail, L"To", 1, x);
368 VariantClear(&x);
371 // pMail->HTMLBody = _bstr_t(L"<b>Feedback:</b><br />");
373 VARIANT x;
374 x.vt = VT_BSTR;
375 x.bstrVal = SysAllocString(L"<b>Feedback:</b><br />");
376 AutoWrap(DISPATCH_PROPERTYPUT, NULL, pMail, L"HTMLBody", 1, x);
377 VariantClear(&x);
380 // Displays a new Inspector object for the item and allows users to click
381 // on the Send button to send the mail manually.
382 // Modal = true makes the Inspector window modal.
383 // pMail->Display(true);
385 VARIANT vtModal;
386 vtModal.vt = VT_BOOL;
387 vtModal.boolVal = VARIANT_TRUE;
388 AutoWrap(DISPATCH_METHOD, NULL, pMail, L"Display", 1, vtModal);
391 // [-or-]
393 // Automatically send the mail without a new Inspector window.
394 // pMail->Send();
395 /*AutoWrap(DISPATCH_METHOD, NULL, pMail, L"Send", 0);*/
398 /////////////////////////////////////////////////////////////////////////
399 // User logs off and quits Outlook.
402 _putws(L"Log off and quit the Outlook application");
404 // pNS->Logoff()
405 AutoWrap(DISPATCH_METHOD, NULL, pNS, L"Logoff", 0);
407 // pOutlookApp->Quit()
408 AutoWrap(DISPATCH_METHOD, NULL, pOutlookApp, L"Quit", 0);
411 /////////////////////////////////////////////////////////////////////
412 // Release the COM objects.
415 if (pMail != NULL)
417 pMail->Release();
419 if (pCts != NULL)
421 pCts->Release();
423 if (pCtFolder != NULL)
425 pCtFolder->Release();
427 if (pNS != NULL)
429 pNS->Release();
431 if (pOutlookApp != NULL)
433 pOutlookApp->Release();
436 // Uninitialize COM for this thread.
437 CoUninitialize();
439 return 0;